﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Text;

namespace LKVMLMApp.StaticClass
{
    public static class Extension
    {
        public static IEnumerable<TResult> LeftJoin<TSource, TInner, TKey, TResult>(this IEnumerable<TSource> source,
                                 IEnumerable<TInner> inner,
                                 Func<TSource, TKey> pk,
                                 Func<TInner, TKey> fk,
                                 Func<TSource, TInner, TResult> result)
        {
            IEnumerable<TResult> _result = Enumerable.Empty<TResult>();

            _result = from s in source
                      join i in inner
                      on pk(s) equals fk(i) into joinData
                      from left in joinData.DefaultIfEmpty()
                      select result(s, left);

            return _result;
        }
        public static TResult NullSafeEval<TSource, TResult>(this TSource source, Expression<Func<TSource, TResult>> expression, TResult defaultValue)
        {
            var safeExp = Expression.Lambda<Func<TSource, TResult>>(
                NullSafeEvalWrapper(expression.Body, Expression.Constant(defaultValue)),
                expression.Parameters[0]);

            var safeDelegate = safeExp.Compile();
            return safeDelegate(source);
        }

        private static Expression NullSafeEvalWrapper(Expression expr, Expression defaultValue)
        {
            Expression obj;
            Expression safe = expr;

            while (!IsNullSafe(expr, out obj))
            {
                var isNull = Expression.Equal(obj, Expression.Constant(null));

                safe =
                    Expression.Condition
                    (
                        isNull,
                        defaultValue,
                        safe
                    );

                expr = obj;
            }
            return safe;
        }

        private static bool IsNullSafe(Expression expr, out Expression nullableObject)
        {
            nullableObject = null;

            if (expr is MemberExpression || expr is MethodCallExpression)
            {
                Expression obj;
                MemberExpression memberExpr = expr as MemberExpression;
                MethodCallExpression callExpr = expr as MethodCallExpression;

                if (memberExpr != null)
                {
                    // Static fields don't require an instance
                    FieldInfo field = memberExpr.Member as FieldInfo;
                    if (field != null && field.IsStatic)
                        return true;

                    // Static properties don't require an instance
                    PropertyInfo property = memberExpr.Member as PropertyInfo;
                    if (property != null)
                    {
                        MethodInfo getter = property.GetGetMethod();
                        if (getter != null && getter.IsStatic)
                            return true;
                    }
                    obj = memberExpr.Expression;
                }
                else
                {
                    // Static methods don't require an instance
                    if (callExpr.Method.IsStatic)
                        return true;

                    obj = callExpr.Object;
                }

                // Value types can't be null
                if (obj.Type.IsValueType)
                    return true;

                // Instance member access or instance method call is not safe
                nullableObject = obj;
                return false;
            }
            return true;
        }
        public static string createSerial()
        {
            Random _random = new Random(Environment.TickCount);
            string alphabets = "ABCDEFGHIJKLMNPQRTUVXYZ";//"O-W-S"
            //string small_alphabets = "abcdefghijklmnpqrtuvxyz";
            string numbers = "1234567890";
            string characters = alphabets  + numbers;

            int length = 9;
            string otp = string.Empty;
            for (int i = 0; i < length; i++)
            {
                string character = string.Empty;
                do
                {
                    int index = _random.Next(0, characters.Length);
                    character = characters.ToCharArray()[index].ToString();
                } while (otp.IndexOf(character) != -1);
                otp += character;
            }
            int _ascii1 = 0;
            int _ascii2 = 0;
            int _ascii3 = 0;
            otp.Substring(0, 3).ToList().ForEach(s => {
                 _ascii1 = _ascii1 +  (int)s;
            });
            otp.Substring(3, 3).ToList().ForEach(s =>
            {
                _ascii2 = _ascii2 + (int)s;
            });
            otp.Substring(6, 3).ToList().ForEach(s => {
                _ascii3 = _ascii3 + (int)s;
            });
            int _lastChar = Convert.ToInt32(_ascii1.ToString().Substring(_ascii1.ToString().Length - 1, 1))
                           + Convert.ToInt32(_ascii2.ToString().Substring(_ascii2.ToString().Length - 1, 1))
                           + Convert.ToInt32(_ascii3.ToString().Substring(_ascii3.ToString().Length - 1, 1));
            otp = otp + _lastChar.ToString().PadLeft(2, '0');
            var _dnow = DateTime.Now;
            return otp;
        }
    }
}
